package bfa.gps;



import java.text.DecimalFormat;
import java.util.ArrayList;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;


public class SpeedometerView extends View {

    //private Paint paint = new Paint();
    private Bitmap sfondo;
    private Bitmap ticks;
    private Bitmap needle;
    RectF r1;
    RectF r2;
    Paint paintR1=new Paint();
    
    Paint paintText=new Paint();
    int textLeftPosition=0;
    
    private ArrayList<SpeedArc> arcs=new ArrayList<SpeedArc>();
    
    private ArrayList<AlarmSpeedArc> alarmArcs=new ArrayList<AlarmSpeedArc>();
    
    
    String noFixTxt="No fix";
    Paint noFixPaint=new Paint();
    Paint noFixpaintText=new Paint();
    int noFixtextLeftPosition=0;
    
    
    Bitmap bmp; 
    
    public SpeedometerView(Context context, AttributeSet attrs) {
    	super(context, attrs);

        
    }

    int w=0;
	int h=0;
    
    float ar=1f;
    private void creaBmp() {

    	if (bmp==null) {
    		
    		w=getWidth();
    		h=getHeight();
    		
    		if (w>h) {
    			w=h;
    		}
    		if (h>w) {
    			h=w;
    		}
    		
	    	Config conf=Bitmap.Config.ARGB_8888; // see other conf types    	
			bmp = Bitmap.createBitmap(w, h,conf); // this creates a MUTABLE bitmap
			Canvas canvas = new Canvas(bmp);
	    	
	        //sfondo = BitmapFactory.decodeResource(getResources(), R.raw.sfondo_speed);
	    	BitmapFactory.Options options = new BitmapFactory.Options();
	    	options.inScaled = false;
	    	
	        sfondo= BitmapFactory.decodeResource(getResources(), R.raw.sfondo_speed,options);        
	        ticks = BitmapFactory.decodeResource(getResources(), R.drawable.ticks,options);        
	        Bitmap needleTemp= BitmapFactory.decodeResource(getResources(), R.drawable.needle,options);
	
	        
	        float radius=(float) (w/2*0.78-3);
	        r1=createRectFromCenterAndRadius(w/2,h/2,radius);
	        r2=createRectFromCenterAndRadius(w/2,h/2,radius*0.98f);
	        
	        addArc(0,50,Color.rgb(0, 0x90, 0));
	        addArc(50,90,Color.rgb(0xF1, 0xE9, 0x00));
	        addArc(90,130,Color.rgb(0xf1, 0xa2, 0x00));
	        addArc(130,150,Color.rgb(0xf1, 0x00, 0x00));

	        
	        ar=w/720f;
	        ruota(canvas,sfondo,0,ar);   

	        // paint all arcs
	        for (SpeedArc s:arcs) {                
	        	if (s.angleFrom<0) {
	        		s.angleFrom=135+convertSpeedToAngle(s.speedFrom);
	        	}
	        	if (s.angleTo<0) {
	        		s.angleTo=135+convertSpeedToAngle(s.speedTo)-s.angleFrom;
	        	}
	        	
	        	canvas.drawArc(
	    			r1, 
	    			s.angleFrom, 
	    			s.angleTo, 
	    			false, 
	    			s.getPaint()
				);
	        }
	        
	        ruota(canvas,ticks,0,ar);   
	        
	        
        	

    		// ***************************************
    		// sound alarms
    		// ***************************************
	        for (AlarmSpeedArc s:alarmArcs) {                
	        	if (s.angleFrom<0) {
	        		s.angleFrom=135+convertSpeedToAngle(s.speedFrom);
	        	}
	        	if (s.angleTo<0) {
	        		s.angleTo=135+convertSpeedToAngle(s.speedTo)-s.angleFrom;
	        	}
	        	s.drawArc(canvas,r2);
	        	
	        }
	        // ***************************************
	        
	        

    		// ***************************************
    		// digital text settings
    		// ***************************************	        	    	
	        paintText.setColor(Color.GRAY);
	        //paintText.setStrokeWidth(4);
	        paintText.setStyle(Paint.Style.STROKE);
	        paintText.setAntiAlias(true);
	        paintText.setTextSize(48);
	        
	        
	        if (! isInEditMode()) {			
				Typeface font = Typeface.createFromAsset(this.getContext().getAssets(), "fonts/Crysta.ttf");
		        paintText.setTypeface(font);
			}

	        float f[]={0f,0f,0f};
	        paintText.getTextWidths("000", f);
	        float textLeftPositionF=f[0]+f[1]+f[2];
	        textLeftPosition=(int) textLeftPositionF;
    		// ***************************************
	        
	        
	        

    		// ***************************************
    		// digital background
    		// ***************************************	        
    		RectF digitalBackground=new RectF((w-textLeftPosition)/2-4,h*3/4+2,(w+textLeftPosition)/2+4,h*3/4-40);
    		Paint digitalBackgroundPaint=new Paint();

    		digitalBackgroundPaint.setColor(Color.BLACK);
    		digitalBackgroundPaint.setStrokeWidth(0);
    		digitalBackgroundPaint.setStyle(Paint.Style.FILL);
    		digitalBackgroundPaint.setAntiAlias(true);
    		
    		canvas.drawRect(digitalBackground, digitalBackgroundPaint);
    		// ***************************************
    		        
	        
    		
    		// ***************************************
    		// needle creation
    		// ***************************************
	        needle=Bitmap.createBitmap(w, h,conf); // this creates a MUTABLE bitmap
	        Canvas canvasN = new Canvas(needle);
	        ruota(canvasN,needleTemp,0,ar);
    		// ***************************************	        
	        

	        
	        
	        
    		// ***************************************
    		// needle creation
    		// ***************************************        	
        	noFixPaint.setColor(Color.RED);
        	noFixPaint.setStyle(Paint.Style.FILL);
        	noFixPaint.setAntiAlias(true);

        	
        	
	        noFixpaintText.setColor(Color.WHITE);
	        noFixpaintText.setStyle(Paint.Style.STROKE);
	        noFixpaintText.setAntiAlias(true);
	        noFixpaintText.setTextSize(36);
	        
	        
//	        if (! isInEditMode()) {			
//				Typeface font = Typeface.createFromAsset(this.getContext().getAssets(), "fonts/Crysta.ttf");
//		        paintText.setTypeface(font);
//			}

	        float[] noPaintFloat= new float[6];
	        noFixpaintText.getTextWidths(noFixTxt, noPaintFloat);
	        float noFixtextLeftPositionF =0;
	        for (int t=0;t<noFixTxt.length();t++) {
	        	noFixtextLeftPositionF+=noPaintFloat[t];
	        }
	        noFixtextLeftPosition=(int) noFixtextLeftPositionF;
        	
        	
        	// ***************************************
    	}
    }
    
    private void ruota(Canvas canvas, Bitmap picture,float rotate,float scale) {
        
    	float x=picture.getWidth()/2;
    	float y=picture.getHeight()/2;
    	
    	if (scale!=0) {
        	if (scale!=1) {
        		canvas.scale(scale, scale);
        	}
        	
        	if (rotate!=0) {
        		canvas.rotate(rotate,x/scale,y/scale);
        	}
        	
            canvas.drawBitmap(picture, 0,0,null);
            
        	if (rotate!=0) {
        		canvas.rotate(-rotate,x/scale,y/scale);
        	}
            
            if (scale!=1) {
            	canvas.scale(1/scale, 1/scale);
            }
            
    		
    	}
    	
    }
    
    
    private RectF createRectFromCenterAndRadius(float x, float y, float radius) {
    	return new RectF(x-radius, y-radius, x+radius,y+radius);
    }
    
    
    String textSpeed="100";
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        creaBmp();
        ruota(canvas,bmp,0,1f);
        
        
        

		int is=(int) getIndicatedSpeed();				
		try {			
			textSpeed = new DecimalFormat("000").format(is);
			canvas.drawText(textSpeed, (w-textLeftPosition)/2,h*3/4,paintText);
			
			
		} catch (NumberFormatException e) {				
		}

        

        // ***************************************
		// Fix/no fix
		// ***************************************               
        if (! isHasFix()) {
        	canvas.drawRect(0,0,noFixtextLeftPosition+4,32,noFixPaint);
        	canvas.drawText(noFixTxt, 2, 28, noFixpaintText);
        }
		// ***************************************	        
		
		
        
        
        ruota(canvas,needle,convertSpeedToAngle(getIndicatedSpeed()),1f);
    }
    
    
	private float indicatedSpeed=0;
    public float getIndicatedSpeed() {
		return indicatedSpeed;
	}

	public void setIndicatedSpeed(float indicatedSpeed) {
		this.indicatedSpeed = indicatedSpeed;
	}
    
    
	private float speedToIndicate=0;
    public float getSpeedToIndicate() {
		return speedToIndicate;
	}

	public void setSpeedToIndicate(float speedToIndicate) {
		this.speedToIndicate = speedToIndicate;
	}

	
	public void fromDesiredToIndicated() {		
		if (smoothMovement) {
			float diff=speedToIndicate-indicatedSpeed;

			if (diff>=maxDiff) {
				indicatedSpeed+=maxDiff;
			} else if (diff>0) {
				indicatedSpeed=speedToIndicate;
			} else if (diff<=-maxDiff) {
				indicatedSpeed-=maxDiff;
			} else if (diff<0) {
				indicatedSpeed=speedToIndicate;
			}
			
			if (indicatedSpeed<0) {
				indicatedSpeed=0;
			} else if (indicatedSpeed>150) {
				indicatedSpeed=150;
			}
			
		} else {
			indicatedSpeed=speedToIndicate;
		}


		invalidate();
	}
	
	private float convertSpeedToAngle(float value) {
		if (value<=0) {
			return 0;
		}

		if (value>=150) {
			return 270;
		}
		
		return value/150*270;
	}
	
	
	
	public boolean isSmoothMovement() {
		return smoothMovement;
	}

	public void setSmoothMovement(boolean smoothMovement) {
		this.smoothMovement = smoothMovement;
	}


	private float maxDiff=2;
	public float getMaxDiff() {
		return maxDiff;
	}

	public void setMaxDiff(float maxDiff) {
		this.maxDiff = maxDiff;
	}


	private boolean smoothMovement=true;
	

	public void addArc(int speedFrom,int speedTo,int color) {
		SpeedArc s=new SpeedArc();
		s.speedFrom=speedFrom;
		s.speedTo=speedTo;
		s.color=color;
		
		arcs.add(s);
	}
	
	public void clearAlarmSpeedArc() {
		alarmArcs.clear();
	}
	public void addAlarmSpeedArc(int speedFrom,int speedTo,int color) {
		AlarmSpeedArc s=new AlarmSpeedArc();
		s.speedFrom=speedFrom;
		s.speedTo=speedTo;
		s.color=color;
		
		alarmArcs.add(s);
	}
	
	public void refreshAll() {
		bmp=null;
	}
	
	public boolean isHasFix() {
		return hasFix;
	}

	public void setHasFix(boolean hasFix) {
		this.hasFix = hasFix;
	}

	private boolean hasFix=false;

}
